<?php
include '../functions/mysql.php';
include '../functions/functions.php';

class Server {
	
	//Cleans the string from bad characters
	private function cleanString($string) {
		$badChars = array("%20", "+");
		$okayChar = " ";
		return str_replace($badChars, $okayChar, $string);
	}
	
	public function serve() {
		$uri = $_SERVER['REQUEST_URI'];
		$uri = $this->cleanString($uri);
		$method = $_SERVER['REQUEST_METHOD'];
		$paths = explode('/', $this->paths($uri));

		array_shift($paths); // Hack; get rid of initials empty string
		$resource = array_shift($paths);
		if ($resource == 'api') {
			$type = array_shift($paths);
			// User specific
			if ($type == 'users') {
				$this->handleTypeUsers($method, $paths);
				// Global
			} else if ($type == 'music') {
				$this->handleTypeMusic($method, $paths);
			} else {
				// We only handle 'user' / 'music'
				header('HTTP/1.1 404 Not Found');
			}
		} else {
			// We only handle resources under 'api'
			header('HTTP/1.1 404 Not Found');
		}
	}

	/*** BEGIN /USER/ specific move to new file?! ***/
	private function handleTypeUsers($method, $res) {
		switch ($method) {
			case 'GET':
				$this->handleUserGet($res);
				break;
			case 'PUT':
			case 'PUSH':
			case 'DELETE':
				$this->handleUserPutPushDelete($method, $res);
				break;
			default:
				header('HTTP/1.1 405 Method Not Allowed');
			header('Allow: GET, PUT, PUSH, DELETE');
			break;
		}
	}

	private function handleUserGet($res) {
		if (empty($res)) {
			// /api/users     Get all users!!
			header('Content-type: application/json');
			echo $this->getAllUsers();
			//$this->putUserListenToSong('fiskjohn','Avenged Sevenfold','TestB','TestTitel','TestD');
		} else {
			if (sizeof($res) > 4) {
				echo 'Too many arguments!';
			} else {
				// /api/users/$user/$userdir/$subdir/$details
				$user 		= array_shift($res);
				$userdir 	= array_shift($res);
				$subdir		= array_shift($res);
				$details 	= array_shift($res);

				if (empty($userdir)) {
					// /api/users/$user
					header('Content-type: application/json');
					echo $this->getUser($user);	
				} else if ($userdir == 'lastplayed') {
					// /api/users/$user/lastplayed
					header('Content-type: application/json');
					echo $this->getLastPlayed($user);
				} else if ($userdir == 'artists' && empty($subdir) ) {
					// /api/users/$user/artists
					header('Content-type: application/json');
					echo $this->getAllUserArtists($user);
				} else if ($userdir == 'songs' && empty($subdir)) {
					// /api/users/$user/songs
					header('Content-type: application/json');
					echo $this->getAllUserSongs($user);
				} else if ($userdir == 'artists') {
					if (empty($details)) {
						// /api/users/$user/artists/$artist
						header('Content-type: application/json');
						echo $this->getUserArtist($user, $subdir);
					} else if ($subdir == 'top') {
						// /api/users/$user/artists/top/$nr
						header('Content-type: application/json');
						echo $this->getTopUserArtists($user, $details);
					} else {
						echo 'Invalid request!';
					}
				} else if ($userdir == 'songs') {
					if ($subdir == 'top' && !empty($details)) {
						// /api/users/$user/songs/top/$nr
						header('Content-type: application/json');
						echo $this->getTopUserSongs($user, $details);
					} else if (!empty($details)) {
						// /api/users/$user/songs/$artist/$title
						header('Content-type: application/json');
						echo $this->getUserSong($user, $subdir, $details);
					} else {
						echo 'Invalid request!';
					}
				} else {
					echo 'Invalid request!';
				}
			}
		}
	}
	private function handleUserPutPushDelete($method, $res) {
		// $user/$type
		$user 	= array_shift($res);
		if (sizeof($res) > 1) {
			//$data = json_decode(file_get_contents('php://input'));
			switch ($method) {
				case 'PUT':
					echo '/api/users/$user PUT - create user';
					break;
				case 'PUSH':
					echo '/api/users/$user PUSH - update user';
					break;
				case 'DELETE':
					echo '/api/users/$user DELETE - delete user';
					break;
			}
		} else {
			echo 'INVALID NUMBER OF ARGUMENTS?!';
			header("HTTP/1.1 404 ERROR KAOS");
		}
	}

	private function handleTypeMusic($method, $res) {
		switch ($method) {
			case 'GET':
				$this->handleMusicGet($res);
				break;
			case 'PUT':
				$this->handleMusicPut($res);
				break;
			default:
				header('HTTP/1.1 405 Method Not Allowed');
			header('Allow: GET, PUT');
			break;
		}
	}

	private function handleMusicGet($res) {
		if (sizeof($res) > 3) {
			echo 'Too many arguments!';
		} else {
			// /api/music/$mdir/$subdir/$details
			$mdir 		= array_shift($res);
			$subdir		= array_shift($res);
			$details 	= array_shift($res);

			if ($mdir == 'artists') {
				if (empty($subdir)) {
					// /api/music/artists
					header('Content-type: application/json');
					echo $this->getAllGlobalArtists();
				} else if ($subdir == 'top' && !empty($details)) {
					// /api/music/artists/top/$nr
					header('Content-type: application/json');
					echo $this->getTopGlobalArtists($details);
				} else if (empty($details)) {
					// /api/music/artists/$artist
					header('Content-type: application/json');
					echo $this->getGlobalArtist($subdir);
				} else {
					echo 'Invalid request!';
				}
			} else if ($mdir == 'songs') {
				if ($subdir == 'top' && !empty($details)) {
					// /api/music/songs/top/$nr
					header('Content-type: application/json');
					echo $this->getTopGlobalSongs($details);
				} else if(!empty($details)) {
					// /api/music/songs/$artist/$title
					header('Content-type: application/json');
					echo $this->getGlobalSong($subdir, $details);
				} else {
					echo 'Invalid request!';
				}
			} else {
				echo 'Invalid request!';
			}
		}
	}

	private function handleMusicPut($res) {
		$data = json_decode(file_get_contents('php://input'), true);
		if (!is_null($data)) {
			if (sizeof($res) > 6) {
				echo 'Too many arguments!';
			} else {
				// /api/music/songs/$mdir/$user/$artist/$title/$album/$genre {"password":"XYZ"}
				$mdir 		= array_shift($res);
				$user		= array_shift($res);
				$artist 	= array_shift($res);
				$title		= array_shift($res);
				$album		= array_shift($res);
				$genre		= array_shift($res);
				if ($mdir == 'songs') {
					if ((!empty($user)) && (!empty($artist))  && (!empty($title)) && (!empty($album)) && (!empty($genre))) {
						$password = $data["password"];
						if ($this->credentialsIsValid($user, $password)) {
							//echo 'Successfully put song!';
							$this->putUserListenToSong($user, $artist, $album, $title, $genre);
							header('HTTP/1.1 200 OK');
						} else {
							header('HTTP/1.1 666 WRONG INFO!!');
						}
					} else {
						header('HTTP/1.1 666 MISSING ARGUMENT');
					}
				} else {
					header('HTTP/1.1 404 Not Found');
				}
			}
		} else  {
			header('HTTP/1.1 404 NO DATA');
		}
	}

	// TEMP
	private function credentialsIsValid($username, $password) {
		$query = "SELECT * FROM Users WHERE username='$username' AND password='$password'";
		$result = mysql_query($query);
		if (!mysql_num_rows($result)) {
			return false;
		} else {
			return true;
		}
	}
	//


	// END JOHN
	private function handle_base($method) {
		switch($method) {
			case 'GET':
				$this->result();
				break;
			default:
				header('HTTP/1.1 405 Method Not Allowed');
			header('Allow: GET');
			break;
		}
	}
	
	//###############################################
	//################### /USER/ ####################
	//###############################################
	//					 ########
	//					 	##
	
	//Last played
	private function getLastPlayed($user) {
		$query = $query = "SELECT lastplayed FROM Users WHERE username='$user'";
		return $this->doQueryToJson($query);
	}

	//GET /api/user/$name/top/artists/$nr		-> nr top artist : listencount (fallande ordning)
	private function getTopUserArtists($name, $nr) {
		$query = "SELECT userid FROM Users WHERE `username`='$name'";
		$result = mysql_query($query) or die ("Error in query: $query " . mysql_error());
		$row = mysql_fetch_assoc($result);
		$query = "SELECT Artist.name AS artist, UserArtistCount.count
				FROM  `UserArtistCount` 
				LEFT JOIN Artist 
				ON UserArtistCount.artistid = Artist.artistid
				WHERE UserArtistCount.userid = '" . $row['userid'] . "' 
				ORDER BY count 
				DESC LIMIT 0 , $nr";
		return $this->doQueryToJson($query);
	}

	//GET /api/user/$name/top/songs/$nr		-> nr top song : listencount (fallande ordning)
	private function getTopUserSongs($name, $nr) {
		$query = "SELECT userid FROM Users WHERE `username`='$name'";
		$result = mysql_query($query) or die ("Error in query: $query " . mysql_error());
		$row = mysql_fetch_assoc($result);
		$query = "SELECT Artist.name AS artist, Song.name AS title, UserSongCount.count
				FROM `UserSongCount` 
				LEFT JOIN Song 
				ON UserSongCount.songid = Song.songid
				LEFT JOIN Artist 
				ON Artist.artistid = UserSongCount.artistid 
				WHERE UserSongCount.userid = '" . $row['userid'] . "' 
				ORDER BY count 
				DESC LIMIT 0 , $nr";
		return $this->doQueryToJson($query);
	}

	//GET /api/user/$name/song/$artist/$title		-> song : listencount
	private function getUserSong($name, $artist, $song) {
		$query = "SELECT userid FROM Users WHERE `username`='$name'";
		$result = mysql_query($query) or die ("Error in query: $query " . mysql_error());
		$row = mysql_fetch_assoc($result);
		$query = "SELECT Artist.name AS artist, Song.name AS title, UserSongCount.count
				  FROM  `UserSongCount` 
				  LEFT JOIN Song ON UserSongCount.songid = Song.songid
				  LEFT JOIN Artist ON Artist.artistid = UserSongCount.artistid
				  WHERE UserSongCount.userid =  '" . $row['userid'] ."'
				  AND Artist.name = '$artist'
				  AND Song.name = '$song'";
		return $this->doQueryToJson($query);
	}

	//GET /api/user/$name/songs			-> all songs : listencount
	private function getAllUserSongs($name) {
		$query = "SELECT userid FROM Users WHERE `username`='$name'";
		$result = mysql_query($query) or die ("Error in query: $query " . mysql_error());
		$row = mysql_fetch_assoc($result);
		$query = "SELECT Artist.name AS artist, Song.name AS title, UserSongCount.count
				FROM `UserSongCount` 
				LEFT JOIN Song 
				ON UserSongCount.songid = Song.songid
				LEFT JOIN Artist 
				ON Artist.artistid = UserSongCount.artistid 
				WHERE UserSongCount.userid = '" . $row['userid'] ."' 
				ORDER BY Song.name";
		return $this->doQueryToJson($query);
	}


	///api/user/$name/artists 			-> all artists : listencount (alfabetisk)
	private function getAllUserArtists($name) {
		$query = "SELECT userid FROM Users WHERE `username`='$name'";
		$result = mysql_query($query) or die ("Error in query: $query " . mysql_error());
		$row = mysql_fetch_assoc($result);
		$query = "SELECT Artist.name AS artist,  UserArtistCount.count
				FROM `UserArtistCount` 
				LEFT JOIN Artist 
				ON Artist.artistid = UserArtistCount.artistid 
				WHERE UserArtistCount.userid = '" . $row['userid'] . "'";
		return $this->doQueryToJson($query);
	}

	//GET /api/user/$name/artist/$artist 		-> artist : listencount
	private function getUserArtist($name, $artist) {
		$query = "SELECT userid FROM Users WHERE `username`='$name'";
		$result = mysql_query($query) or die ("Error in query: $query " . mysql_error());
		$row = mysql_fetch_assoc($result);
		$query = "SELECT Artist.name AS artist, UserArtistCount.count
				  FROM  `UserArtistCount` 
				  LEFT JOIN Artist ON Artist.artistid = UserArtistCount.artistid
				  WHERE UserArtistCount.userid =  '" . $row['userid'] ."'
				  AND Artist.name = '$artist'";
		return $this->doQueryToJson($query);
	}

	//GET all users
	private function getAllUsers(){
		$query = "SELECT username, userid, lastplayed FROM Users ORDER BY username";
		return $this->doQueryToJson($query);
	}

	#####################################################
	##################### Music Global ##################

	//################### Artists ######################
	//GET /api/music/artist/$artist			-> artist : listencount
	private function getGlobalArtist($artist) {
		$query = "SELECT name AS artist, count
				  FROM  `Artist` 
				  WHERE name =  '$artist'";
		return $this->doQueryToJson($query);
	}

	//GET /api/music/artist/			-> all artist : listencount
	private function getAllGlobalArtists() {
		$query = "SELECT name AS artist, count
				  FROM  `Artist`
				  ORDER BY name";
		return $this->doQueryToJson($query);
	}

	//GET /api/music/top/artists/$nr		-> nr top artist : listencount (fallande ordning)
	private function getTopGlobalArtists($nr) {
		$query = "SELECT name AS artist, count
				  FROM  `Artist`
				  ORDER BY count DESC
				  LIMIT 0, $nr";
		return $this->doQueryToJson($query);
	}

	//################# Song ###################################

	//GET /api/music/song/$artist/$title
	private function getGlobalSong($artist, $title) {
		$query = "SELECT Artist.name AS artist, Song.name AS title, Song.count
				FROM `Song`
				LEFT JOIN Artist 
				ON Artist.artistid = Song.artistid
				WHERE Artist.name =  '$artist'
				AND Song.name =  '$title'";
		return $this->doQueryToJson($query);
	}

	//GET /api/music/top/songs/$nr
	private function getTopGlobalSongs($nr) {
		$query = "SELECT Artist.name AS artist, Song.name AS title, Song.count
				FROM  `Song` 
				LEFT JOIN Artist 
				ON Artist.artistid = Song.artistid
				ORDER BY Song.count DESC
				LIMIT 0 , $nr";
		return $this->doQueryToJson($query);
	}


	///////////////////// Music Global //////////////////
	/////////////////////////////////////////////////////
	//Generic function
	private function doQueryToJson($query) {
		$result = mysql_query($query) or die ("Error in query: $query " . mysql_error());
		if ($this->dbQuery($result) == true) {
			$counter = 1;
			while($row = mysql_fetch_assoc($result)) {

				foreach($row as $key => $value) {

					$arr[$key] = $value;
				}
				$main_arr[$counter] = $arr;
				$counter++;
			}

			$json = json_encode($main_arr);
			return $json;
		}
	}

	//Check if there was any result
	private function dbQuery($result) {
		$num_results = mysql_num_rows($result);
		if ($num_results > 0){
			return true;
		} else{
			header('HTTP/1.1 404 failed');
			return;
		}
	}

	private function getUser($name) {
		$main_arr = array();
		$query = "SELECT username, userid, lastplayed FROM Users WHERE `username`='$name'";
		return $this->doQueryToJson($query);
	}

	private function putUser($name) {
		if ($this->checkIfUserExist($name)) {
			header('HTTP/1.1 409 Username conflict');
			return;
		}
		$data = json_decode(file_get_contents('php://input'));
		if (is_null($data)) {
			header('HTTP/1.1 400 Bad Request');
			return;
		} else {
			echo 'fisk';
			if(is_object($data)) {
				$data = get_object_vars($data);
				if ($this->checkIfEmailExist($data['email'])) {
					header('HTTP/1.1 409 Email conflict');
					return;
				}
				$query = "INSERT INTO Users (username, email, password) VALUES('$name', '" . $data['email'] . "', '" . MD5($data['password']) . "')";
				mysql_query($query) or die ("Error in query: $query " . mysql_error());
			}
		}
	}
	
	//Checks if username exists in database
	private function checkIfUserExist($username) {
		$checkuser = mysql_query("SELECT * FROM Users WHERE username='$username'");
		$username_exist = mysql_num_rows($checkuser);

		if($username_exist > 0){
			return true;
		} else {
			return false;
		}
	}
	//Checks if email exists in database
	private function checkIfEmailExist($email) {
		$checkemail = mysql_query("SELECT * FROM Users WHERE email='$email'");
		$email_exist = mysql_num_rows($checkemail);
		if($email_exist > 0){
			return true;
		} else {
			return false;
		}
	}
	
	//Updates user
	private function postUser($name) {
		if ($this->checkIfUserExist($name)) {
			$data = json_decode(file_get_contents('php://input'));
			if (is_null($data)) {
				header('HTTP/1.1 400 Bad Request');
				return;
			} else {
				if(is_object($data)) {
					$data = get_object_vars($data);
					$query = "SELECT * FROM Users WHERE username='$name'";
					$result = mysql_query($query);
					$row = mysql_fetch_array($result);
					if($data['email'] == null) {
						$data['email'] = $row['email'];
					}
					if($data['password'] == null) {
						$data['password'] = $row['password'];
					}
					$query = "UPDATE `Users` SET email='" . $data['email'] . "', password='" . MD5($data['password']) . "' WHERE username='$name'";
					mysql_query($query) or die ("Error in query: $query " . mysql_error());
				}
			}
		} else {
			header('HTTP/1.1 400 Bad Request');
			return;
		}
	}

	//Delete user
	private function deleteUser($name) {
		if ($this->checkIfUserExist($name)) {
			$query = "DELETE FROM `Users` WHERE username='$name'";
			mysql_query($query);
		} else {
			header('HTTP/1.1 400 Bad Request');
			return;
		}
	}
	##
	########
	//###############################################
	//################### /USER/ ####################
	//###############################################

	//###############################################
	//################### /Artist/ ##################
	//###############################################
	//					 ##########
	//					 	####

	//Adds genre, album, artist, track, listen counts.
	private function putUserListenToSong($user, $artist, $album, $title, $genre) {
		$query = "SELECT userid FROM Users WHERE username='$user'";
		$result = mysql_query($query);
		$row = mysql_fetch_array($result);
		$userid = $row['userid'];
		$this->addLastPlayed($userid, $artist, $title);
		$genreid = $this->addGenre($genre);
		$artistid = $this->addArtist($artist, $genreid);
		$albumid = $this->addAlbum($album, $artistid, $genreid);
		$songid = $this->addSong($title, $albumid, $artistid, $genreid);
		$this->addUserSongRelation($userid, $songid, $artistid);
		$this->addUserArtistRelation($userid, $artistid);
		$this->addUserListenCount($userid, $artistid, $songid);
		$this->addGlobalListenCount($artistid, $songid);
	}
	
	private function addLastPlayed($userid, $artist, $title){
		$string = $artist . ' - ' . $title;
		$query = "UPDATE `Users` SET `lastplayed`='$string' WHERE `userid`='$userid'";
		mysql_query($query);
	}

	private function addArtist($artist, $genreid) {
		$query = "INSERT INTO `Artist`(`name`, `genreid`)
				VALUES ('$artist','$genreid')"; 
		mysql_query($query);

		$query = "SELECT artistid FROM Artist
				WHERE `name`='$artist'";
		$result = mysql_query($query) or die ("Error in query: $query " . mysql_error());
		$row = mysql_fetch_assoc($result);
		return $row['artistid'];
	}

	private function addAlbum($album, $artistid, $genreid){
		$query = "INSERT INTO `Album`(`artistid`, `name`, `genreid`)
				VALUES ('$artistid', '$album','$genreid')"; 
		mysql_query($query);

		$query = "SELECT albumid FROM Album
				WHERE `name`='$album'";
		$result = mysql_query($query) or die ("Error in query: $query " . mysql_error());
		$row = mysql_fetch_assoc($result);
		return $row['albumid'];
	}

	private function addSong($title, $albumid, $artistid, $genreid) {
		$query = "SELECT * FROM Song
				WHERE `name`='$title'
				AND artistid = '$artistid'";
		$result = mysql_query($query) or die ("Error in query: $query " . mysql_error());
		$song_exist = mysql_num_rows($result);
		if($song_exist){
			$row = mysql_fetch_assoc($result);
			return $row['songid'];
		} else {
			$query = "INSERT INTO `Song`(`artistid`, `albumid`, `name`)
					VALUES ('$artistid', '$albumid','$title')"; 
			mysql_query($query);

			$query = "SELECT songid FROM Song
					WHERE `name`='$title'
					AND `artistid`='$artistid'";
			$result = mysql_query($query) or die ("Error in query: $query " . mysql_error());
			$row = mysql_fetch_assoc($result);
			return $row['songid'];
		}
	}

	private function addUserSongRelation($userid, $songid, $artistid) {
		$query = "SELECT * FROM UserSongCount
				WHERE `userid`='$userid'
				AND songid = '$songid'";
		$result = mysql_query($query) or die ("Error in query: $query " . mysql_error());
		$relation_exist = mysql_num_rows($result);
		echo 'dask';
		echo $relation_exist;
		echo 'ad';
		if(!$relation_exist){
			echo 'fisk';
			$query = "INSERT INTO  `MyMS`.`UserSongCount` (`songid` , `userid`, `artistid`)
					VALUES ('$songid',  '$userid',  '$artistid')";
			mysql_query($query);
		}
	}

	private function addUserArtistRelation($userid, $artistid) {
		$query = "SELECT * FROM UserArtistCount
				WHERE userid = '$userid'
				AND artistid = '$artistid'";
		$result = mysql_query($query) or die ("Error in query: $query " . mysql_error());
		$relation_exist = mysql_num_rows($result);
		if(!$relation_exist){
			$query = "INSERT INTO  `MyMS`.`UserArtistCount` (`userid`, `artistid`)
					VALUES ('$userid',  '$artistid')";
			mysql_query($query);
		}
	}

	private function getGenreId($genre) {
		$query = "SELECT 'genreid' FROM Genre WHERE `genre`='$genre'";
		$result = mysql_query($query) or die ("Error in query: $query " . mysql_error());
		$row = mysql_fetch_assoc($result);
		return $row['genreid'];
	}

	private function addGenre($genre) {
		$query = "INSERT INTO `Genre`(`genre`) VALUES ('$genre')";
		mysql_query($query);

		$query = "SELECT genreid FROM Genre WHERE `genre`='$genre'";
		$result = mysql_query($query) or die ("Error in query: $query " . mysql_error());
		$row = mysql_fetch_assoc($result);
		return $row['genreid'];
	}


	private function addGlobalListenCount($artistid, $songid){
		$query ="UPDATE Artist
		LEFT JOIN Song
		ON Artist.artistid = Song.artistid
		SET Artist.count = Artist.count+1,
		Song.count = Song.count+1
		WHERE Artist.artistid = '$artistid'
		AND Song.songid = '$songid'";
		mysql_query($query);
	}

	private function addUserListenCount($userid, $artistid, $songid) {
		$query = "UPDATE UserArtistCount
		LEFT JOIN UserSongCount
		ON UserArtistCount.artistid = UserSongCount.artistid
		SET UserArtistCount.count = UserArtistCount.count+1,
		UserSongCount.count = UserSongCount.count+1
		WHERE UserArtistCount.artistid = '$artistid'
		AND UserSongCount.songid = '$songid'
		AND UserSongCount.userid = '$userid'";
		mysql_query($query);
	}


	private function paths($url) {
		$uri = parse_url($url);
		return $uri['path'];
	}

	/**
	 * Displays a list of all contacts.
	 */
	private function result() {
		header('Content-type: application/json');
		echo json_encode($this->contacts);
	}
}
$server = new Server;
$server->serve();
?>
